package com.team.teamuserservice.service.impl;

import cn.hutool.json.JSONUtil;
import com.team.teamuserservice.entity.dto.DelayRescueMessage;
import com.team.teamuserservice.entity.dto.UserLocation;
import com.team.teamuserservice.entity.po.BizRescueTask;
import com.team.teamuserservice.service.BroadcastService;
import com.team.teamuserservice.service.IBizRescueTaskService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.List;

import static com.team.teamuserservice.websocket.RescueWebsocketHandler.rescueMap;

/**
 * 广播服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class BroadcastServiceImpl implements BroadcastService {

    private final RedisTemplate<String, Object> redisTemplate;
    
    private static final String MERCHANT_KEY = "rescueMerchant";

    private final IBizRescueTaskService bizRescueTaskService;

    @Override
    public void broadcastToMerchants(DelayRescueMessage delayRescueMessage, double distance) throws IOException {

        //扩大之前先看一下是否用户已经取消订单 3,或者是不是已经有商家接单1 , 有了就取消 , 没有就广播 , 就算出现商家已经接单或者取消但是我还在广播中，那也无所谓继续广播 , 商家抢单是会有保证判断
        List<BizRescueTask> list = bizRescueTaskService.lambdaQuery()
                .eq(BizRescueTask::getId, delayRescueMessage.getRescueTaskId()).list();
        if (list.isEmpty()) return;
        BizRescueTask rescueTask = list.get(0);
        //如果不是待接单
        if (!rescueTask.getStatus().equals("0")){
            return;
        }

        GeoResults<RedisGeoCommands.GeoLocation<Object>> geos = redisTemplate.opsForGeo().radius(MERCHANT_KEY,
                    new Circle(new Point(delayRescueMessage.getUserLocation().getLongitude(), delayRescueMessage.getUserLocation().getLatitude()), distance)
            );

        if (geos != null) {
            for (GeoResult<RedisGeoCommands.GeoLocation<Object>> geoResult : geos) {
                String merchantIdStr = geoResult.getContent().getName().toString();
                //解析戳来商家的id
                Long merchantId = Long.valueOf(merchantIdStr);

                // 获取该商家的 session
                String jsonStr = JSONUtil.toJsonStr(delayRescueMessage.getUserLocation());
                WebSocketSession webSocketSession = rescueMap.get(merchantId);

                // 发送消息给该商家
                if (webSocketSession != null && webSocketSession.isOpen()) {
                    webSocketSession.sendMessage(new TextMessage(jsonStr));
                    log.info("已向商家 {} 发送 {}m 广播消息", merchantId, distance);
                }
            }
        }
    }

    @Override
    public void broadcastTo5kmMerchants(DelayRescueMessage delayRescueMessage) throws IOException {
        log.info("开始5km广播，用户ID: {}", delayRescueMessage.getUserLocation().getUserId());
        broadcastToMerchants(delayRescueMessage, 5000.0);
    }

    @Override
    public void broadcastTo10kmMerchants(DelayRescueMessage delayRescueMessage) throws IOException {
        log.info("开始10km广播，用户ID: {}", delayRescueMessage.getUserLocation().getUserId());
        broadcastToMerchants(delayRescueMessage, 10000.0);
    }
} 